/*
 * Get the initial population which includes 10 feasible solutions(individuals).
 * Do the crossover operation to the first two solutions;
 * Do the crossover operation to the random two solutions;
 * Do the mutation operation to the third solutions,
 * until there is no better solution can be found within 10 times' feasible iterations,
 * at this time, if the remaining energy is above 500,
 * do the small exploration, else do the big exploration;
 * if within 10 times' feasible exploring iterations, there is no better solution can be 
 * found, jump out the exploring, else do the crossover to the better solution.
 * If remaining energy is under 500, do the big exploration, which aims to escape from the
 * local optimal. If within 10 times' feasible exploring iterations, there is no better 
 * solution can be found, jump out the exploring, else do the crossover to the better solution,
 * if the best time found so far under 210.0 seconds, we will fix the strategy and do 20 
 * times' feasible mutation to the pacing array to locate the local optimal. if can not 
 * find the better one, we will fix the pacing and do 10 times' feasible mutation to the 
 * strategy array to locate the local optimal. 
 * Further more,)we can adjust the pacing and strategy arrays according to the remaining
 * energy of corresponding player (not implemented yet in this code).
 */
package ev;
import java.util.ArrayList;


import java.util.Arrays;
import java.util.Random;

import ev.initial.Individual;
import ev.initial.Initial;
import ev.operator.Crossover;
import ev.operator.Cycle;
import ev.operator.MidCycle;
import ev.operator.Mutation;
import ev.operator.Swap;
import ev.operator.bigSwap;
import ev.selection.NewSimpleSelection;
import ev.selection.Selection;
import ev.selection.SimpleSelection;

import TeamPursuit.*;

public class EA_Team_Women3 implements Team_Women {

	public void emulation() {
		SimulationResult result = null;
        WomensTeamPursuit womensTeamPursuit = new WomensTeamPursuit();
//        try {				
//			womensTeamPursuit.setHeight(0, 1.65);
//			womensTeamPursuit.setWeight(0, 70.0);
//			womensTeamPursuit.setMeanMaximumPower(0, 5.5);
//			
//			womensTeamPursuit.setHeight(2, 1.55);
//			womensTeamPursuit.setWeight(2, 60.0);
//			womensTeamPursuit.setMeanMaximumPower(2, 4.5);
//			
//			
//			// Simulate event with the default strategies
//			//result = womensTeamPursuit.simulate(DEFAULT_WOMENS_TRANSITION_STRATEGY, DEFAULT_WOMENS_PACING_STRATEGY);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
		//initial population whose size is three
        ArrayList<Individual> p=Initial.data;
        Selection s=new SimpleSelection();
        Selection ns=new NewSimpleSelection();
        p=s.select(p,10);
		int times=3000;
		int matingTimes=3;
		Mutation m=new Swap();
		Crossover c=new MidCycle();
		Random r=new Random();
		int count=0;
		double oldTime;
		while(times>0){
			System.out.println("times= "+times);
			oldTime=p.get(0).getTime();
			//Do the crossover operation to the first two solutions
			for(int i=0;i<matingTimes;i++){
				Individual p1=p.get(0).copy();
				Individual p2=p.get(1).copy();				
				boolean[] a=c.cross(p1.getStrategy(), p2.getStrategy());
				int[] b=c.cross(p1.getPacing(), p2.getPacing());
				Individual newIndiv=new Individual(a,b);				
				try {
	        		result = womensTeamPursuit.simulate(a, b);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(!isValid(result)){i--;}
				else{
					newIndiv.setTime(result.getFinishTime());
					p.add(newIndiv);
					//System.out.println("p.sizeC1= "+p.size());
				}
			}
			
			//Do the crossover operation to the random two solutions
			for(int i=0;i<matingTimes;i++){
				Individual p4=p.get(r.nextInt(10)).copy();
				Individual p5=p.get(r.nextInt(10)).copy();				
				boolean[] d=c.cross(p4.getStrategy(), p5.getStrategy());
				int[] e=c.cross(p4.getPacing(), p5.getPacing());
				Individual newIndiv=new Individual(d,e);				
				try {
	        		result = womensTeamPursuit.simulate(d, e);
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				if(!isValid(result)){i--;}
				else{
					newIndiv.setTime(result.getFinishTime());
					p.add(newIndiv);
				}
				//System.out.println("p.sizeC2= "+p.size());
			}
			
			//Do the mutation operation to the third solutions
			for(int i=0;i<matingTimes;i++){
				Individual p3=p.get(2).copy();
				boolean[] ma=m.mutate(p3.getStrategy());
				int[] mb=m.mutate(p3.getPacing());
				Individual newIndiv=new Individual(ma,mb);
				try {
	        		result = womensTeamPursuit.simulate(ma, mb);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(!isValid(result)){i--;}
				else{
					newIndiv.setTime(result.getFinishTime());
					p.add(newIndiv);
				}

				//System.out.println("p.sizeM= "+p.size());
			}
			//System.out.println("p.sizeM= "+p.size());
			p=s.select(p, 10);
			try {
        		result = womensTeamPursuit.simulate(p.get(0).getStrategy(), p.get(0).getPacing());
			} catch (Exception e) {
				e.printStackTrace();
			}

			if(p.get(0).getTime()==oldTime){
				count++;
			}else{
				count=0;
			}
			if(count==10){
				System.out.println("adding new individual");
				p=ns.select(p, 10);
			}
			
			
			for(int i=0;i<p.size();i++){
				System.out.println(p.get(i).toString());
			}
			System.out.println(result);
			times--;
		}
		System.out.println("-----------------------------");
		System.out.println(p.get(0));
	}
	
	private ArrayList<Individual> smallExploiting(ArrayList<Individual> p) {
		SimulationResult result = null;
        WomensTeamPursuit womensTeamPursuit = new WomensTeamPursuit();
        try {				
			womensTeamPursuit.setHeight(0, 1.65);
			womensTeamPursuit.setWeight(0, 70.0);
			womensTeamPursuit.setMeanMaximumPower(0, 5.5);
			
			womensTeamPursuit.setHeight(2, 1.55);
			womensTeamPursuit.setWeight(2, 60.0);
			womensTeamPursuit.setMeanMaximumPower(2, 4.5);
			
			
			// Simulate event with the default strategies
			//result = womensTeamPursuit.simulate(DEFAULT_WOMENS_TRANSITION_STRATEGY, DEFAULT_WOMENS_PACING_STRATEGY);
		} catch (Exception e) {
			e.printStackTrace();
		}
        Random r=new Random();
        Selection s=new SimpleSelection();
		Individual p3=p.get(0).copy();
		double time=p3.getTime();
		boolean[] strategy=p3.getStrategy();
		final boolean[] strategy1=new boolean[p3.getStrategy().length];
		for(int k=0;k<strategy1.length;k++){
			strategy1[k]=p3.getStrategy()[k];
		}
		int[] pacing=p3.getPacing();
		final int[] pacing1=new int[p3.getPacing().length];
		for(int k=0;k<pacing1.length;k++){
			pacing1[k]=p3.getPacing()[k];
		}
		for(int i=0;i<strategy.length;i++){
			if(strategy[i]){
				strategy[i]=false;
			}else{strategy[i]=true;}
			
			try {
        		result = womensTeamPursuit.simulate(strategy, pacing);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			
			
			for(int j=0;j<pacing.length;j++){
				pacing[j]=r.nextInt(801)+200;			
				try {
	        		result = womensTeamPursuit.simulate(strategy, pacing);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if(isValid(result)&&result.getFinishTime()<time){
					Individual newIndiv=new Individual(strategy,pacing);
					newIndiv.setTime(result.getFinishTime());
					p.add(newIndiv);
					p=s.select(p, 3);
					System.out.println("finditfinditfinditfinditfinditfinditfinditfinditfinditfindit");
					System.out.println("p.get(1)= "+p.get(1));
					System.out.println("p.get(2)= "+p.get(2));
					System.out.println("p.get(0)= "+p.get(0));
					System.out.println("finditfinditfinditfinditfinditfinditfinditfinditfinditfindit");
					return p;
				}else{
					//System.out.println("yesssssssssssssssssssssssssssssssssssssssssssss");
					//System.out.println("invalidStrategy= "+Arrays.toString(strategy));
					//System.out.println("invalidPacing= "+Arrays.toString(pacing));
					pacing=pacing1;
				}		
			}
			
			
			
			
			if(isValid(result)&&result.getFinishTime()<time){
				Individual newIndiv=new Individual(strategy,pacing);
				newIndiv.setTime(result.getFinishTime());
				p.add(newIndiv);
				p=s.select(p, 3);
				System.out.println("smallExploitingsmallExploitingsmallExploiting");
				System.out.println("p.get(1)= "+p.get(1));
				System.out.println("p.get(2)= "+p.get(2));
				System.out.println("p.get(0)= "+p.get(0));
				System.out.println("smallExploitingsmallExploitingsmallExploiting");
				return p;
			}else{
				//System.out.println("noooooooooooooooooooooooooooooooooooooooooooooo");
				//System.out.println("p.get(0)= "+p.get(0));
				strategy=strategy1;
			}		
		}

		return p;
	}


	private boolean isValid(SimulationResult result){
		if(result.getProportionCompleted() < 0.9999998){
			return false;
		}else{
			return true;
		}
	}
	

}